# -*- coding: utf-8 -*-
"""
DTO/序列化工具，负责统一报表模块的返回结构。
"""
from __future__ import annotations

import json
from datetime import datetime
from typing import Any, Dict, List, Optional

from app.blueprints.reports.registry.registry import TemplateRegistry


def _parse_json(value: Any, default=None):
    if value is None:
        return default
    if isinstance(value, (dict, list)):
        return value
    if isinstance(value, str):
        try:
            return json.loads(value)
        except Exception:
            return default if default is not None else value
    return default if default is not None else value


def _format_datetime(value: Any) -> Optional[str]:
    if not value:
        return None
    if isinstance(value, datetime):
        return value.strftime("%Y-%m-%d %H:%M:%S")
    return str(value)


def _merge_dict(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
    merged = dict(base or {})
    merged.update(override or {})
    return merged


def _cron_readable(expr: Optional[str]) -> Optional[str]:
    if not expr or not isinstance(expr, str):
        return None
    parts = expr.strip().split()
    if len(parts) not in (5, 6):
        return expr

    if len(parts) == 5:
        minute, hour, day, month, dow = parts
    else:
        second, minute, hour, day, month, dow = parts

    def _any(v):
        return v in ("*", "*/1", "?")

    if _any(month) and _any(day) and _any(dow) and not _any(hour) and not _any(minute):
        return f"每天 {hour}点{minute}分"
    if _any(month) and _any(day) and not _any(dow):
        return f"每周{dow} {hour}点{minute}分"
    if _any(month) and not _any(day):
        return f"每月{day}日 {hour}点{minute}分"
    if minute.startswith("*/") and _any(hour) and _any(day) and _any(month) and _any(dow):
        return f"每{minute.replace('*/', '')}分钟"
    if hour.startswith("*/") and minute == "0":
        return f"每{hour.replace('*/', '')}小时"
    return expr


def build_template_payload(row: Dict[str, Any]) -> Dict[str, Any]:
    descriptor = TemplateRegistry.get(row.get("template_code"))
    default_params = _parse_json(row.get("default_params"), {}) or {}
    output_formats = _parse_json(row.get("output_formats"), []) or []

    if descriptor:
        default_params = _merge_dict(descriptor.default_params, default_params)
        if not output_formats:
            output_formats = descriptor.output_formats

    payload = {
        **row,
        "param_schema": _parse_json(row.get("param_schema"), {}),
        "default_params": default_params,
        "output_formats": output_formats,
        "created_at": _format_datetime(row.get("created_at")),
        "updated_at": _format_datetime(row.get("updated_at")),
    }

    if descriptor:
        payload.setdefault("template_name", descriptor.name)
        payload.setdefault("template_group", descriptor.group)
        payload["display_fields"] = descriptor.display_fields

    return payload


def build_config_payload(row: Dict[str, Any]) -> Dict[str, Any]:
    descriptor = TemplateRegistry.get(row.get("template_code"))
    params = _parse_json(row.get("params"), {})
    output_formats = row.get("output_formats")
    output_formats = (
        output_formats if isinstance(output_formats, list) else _parse_json(output_formats, [])
    )

    payload = {
        **row,
        "params": params,
        "output_formats": output_formats or (descriptor.output_formats if descriptor else []),
        "created_at": _format_datetime(row.get("created_at")),
        "updated_at": _format_datetime(row.get("updated_at")),
        "schedule_cron_readable": _cron_readable(row.get("schedule_cron")),
    }

    if descriptor:
        payload["template_meta"] = {
            "code": descriptor.code,
            "name": descriptor.name,
            "group": descriptor.group,
            "display_fields": descriptor.display_fields,
        }

    return payload


def build_run_payload(row: Dict[str, Any]) -> Dict[str, Any]:
    payload = {
        **row,
        "params": _parse_json(row.get("params"), {}),
        "summary": _parse_json(row.get("summary"), {}),
        "notify_channels": _parse_json(row.get("notify_channels"), []),
        "notify_params": _parse_json(row.get("notify_params"), {}),
        "created_at": _format_datetime(row.get("created_at")),
        "updated_at": _format_datetime(row.get("updated_at")),
        "finished_at": _format_datetime(row.get("finished_at")),
        "time_start": _format_datetime(row.get("time_start")),
        "time_end": _format_datetime(row.get("time_end")),
    }
    return payload


def build_notification_payload(row: Dict[str, Any]) -> Dict[str, Any]:
    return {
        **row,
        "wecom_mention": _parse_json(row.get("wecom_mention"), []),
        "email_recipients": _parse_json(row.get("email_recipients"), []),
        "email_cc": _parse_json(row.get("email_cc"), []),
        "extra": _parse_json(row.get("extra"), {}),
        "created_at": _format_datetime(row.get("created_at")),
        "updated_at": _format_datetime(row.get("updated_at")),
    }


